From: Antonio Nino Diaz Date: Fri, 13 Jul 2018 08:27:16 +0000 (+0100) Subject: rpi3: Introduce hardware RNG driver X-Git-Url: http://git.openwrt.org/%22https:/collectd.org//%22/%22https:/collectd.org/%22?a=commitdiff_plain;h=4ad2696d888400a9990f8c7a0fa57af743f01515;p=project%2Fbcm63xx%2Fatf.git rpi3: Introduce hardware RNG driver Note that this is a non-secure RNG. This is only useful for educational purposes. Change-Id: If359c8d0f755ef8e416986de7fbca34679a523e1 Signed-off-by: Antonio Nino Diaz --- diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h index a83a0ad1..1a26053b 100644 --- a/plat/rpi3/rpi3_hw.h +++ b/plat/rpi3/rpi3_hw.h @@ -58,6 +58,24 @@ */ #define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) +/* + * Hardware random number generator. + */ +#define RPI3_IO_RNG_OFFSET ULL(0x00104000) +#define RPI3_RNG_BASE (RPI3_IO_BASE + RPI3_IO_RNG_OFFSET) +#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) +#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) +#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) +#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) +/* Enable/disable RNG */ +#define RPI3_RNG_CTRL_ENABLE U(0x1) +#define RPI3_RNG_CTRL_DISABLE U(0x0) +/* Number of currently available words */ +#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) +#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) +/* Value to mask interrupts caused by the RNG */ +#define RPI3_RNG_INT_MASK_DISABLE U(0x1) + /* * Serial port (called 'Mini UART' in the BCM docucmentation). */ diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h index 9d1744e3..91b7add8 100644 --- a/plat/rpi3/rpi3_private.h +++ b/plat/rpi3/rpi3_private.h @@ -33,6 +33,9 @@ uint32_t rpi3_get_spsr_for_bl33_entry(void); /* IO storage utility functions */ void plat_rpi3_io_setup(void); +/* Hardware RNG functions */ +void rpi3_rng_read(void *buf, size_t len); + /* VideoCore firmware commands */ int rpi3_vc_hardware_get_board_revision(uint32_t *revision); diff --git a/plat/rpi3/rpi3_rng.c b/plat/rpi3/rpi3_rng.c new file mode 100644 index 00000000..111b3b6c --- /dev/null +++ b/plat/rpi3/rpi3_rng.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "rpi3_hw.h" + +/* Initial amount of values to discard */ +#define RNG_WARMUP_COUNT U(0x40000) + +static void rpi3_rng_initialize(void) +{ + uint32_t int_mask, ctrl; + + /* Return if it is already enabled */ + ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET); + if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) { + return; + } + + /* Mask interrupts */ + int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET); + int_mask |= RPI3_RNG_INT_MASK_DISABLE; + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask); + + /* Discard several values when initializing to give it time to warmup */ + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT); + + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET, + RPI3_RNG_CTRL_ENABLE); +} + +static uint32_t rpi3_rng_get_word(void) +{ + size_t nwords; + + do { + /* Get number of available words to read */ + nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET) + >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT) + & RPI3_RNG_STATUS_NUM_WORDS_MASK; + } while (nwords == 0U); + + return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET); +} + +void rpi3_rng_read(void *buf, size_t len) +{ + uint32_t data; + size_t left = len; + uint32_t *dst = buf; + + assert(buf != NULL); + assert(len != 0U); + assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0); + + rpi3_rng_initialize(); + + while (left >= sizeof(uint32_t)) { + data = rpi3_rng_get_word(); + *dst++ = data; + left -= sizeof(uint32_t); + } + + if (left > 0U) { + data = rpi3_rng_get_word(); + memcpy(dst, &data, left); + } +}